/*
    Dao FLTK2
    Copyright (C) 2010 Belousov Oleg <belousov.oleg@gmail.com>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <fltk/Widget.h>
#include <fltk/draw.h>
#include <fltk/events.h>
#include <dao.h>
#include <string.h>

#include "widget.h"
#include "drawbox.h"

extern DaoVmSpace  *VmSpace;

using namespace fltk;

class CDrawBox : public Widget {
public:
    CDrawBox(int x, int y, int w, int h, const char* label=0);

    void draw();
    int handle(int event);
};

CDrawBox::CDrawBox(int x,int y,int w,int h, const char* label) : Widget(x, y, w, h, label) {
};

void CDrawBox::draw() {
    Widget::draw();

    DaoCData    *cdata = (DaoCData*) user_data();
    DaoObject   *obj = DaoCData_GetObject(cdata);
    DValue      val = DaoObject_GetField(obj, "draw");

    if (val.t == DAO_ROUTINE) {
        DaoVmProcess 	*vmp = DaoVmSpace_AcquireProcess(VmSpace);

	fltk::push_clip(0, 0, w(), h());
        DaoVmProcess_Call(vmp, val.v.routine, obj, NULL, 0);

	fltk::pop_clip();
	fltk::line_style(fltk::SOLID | fltk::CAP_SQUARE, 1);

        DaoVmSpace_ReleaseProcess(VmSpace, vmp);
    }
}

int CDrawBox::handle(int event) {
    DaoCData    *cdata = (DaoCData*) user_data();
    DaoObject   *obj = DaoCData_GetObject(cdata);
    DValue      val = DaoObject_GetField(obj, "handle");

    if (val.t == DAO_ROUTINE) {
        DValue  item;
        DaoMap  *map = DaoMap_New(0);

	switch (event) {
	    case fltk::PUSH:
    		DaoMap_InsertMBS(map, "x", DValue_NewInteger(fltk::event_x()));
    		DaoMap_InsertMBS(map, "y", DValue_NewInteger(fltk::event_y()));
    		DaoMap_InsertMBS(map, "button", DValue_NewInteger(fltk::event_button()));
    		DaoMap_InsertMBS(map, "clicks", DValue_NewInteger(fltk::event_clicks()));
		break;

	    case fltk::SHORTCUT: {
		char	*text;
	
		switch (fltk::event_key()) {
		    case fltk::EscapeKey: 	text = "Escape";	break;
		    case fltk::BackSpaceKey: 	text = "BackSpace";	break;
		    case fltk::TabKey: 		text = "Tab";		break;
		    case fltk::ReturnKey: 	text = "Return";	break;
		    case fltk::PrintKey: 	text = "Print";		break;
		    case fltk::ScrollLockKey: 	text = "ScrollLock";	break;
		    case fltk::PauseKey: 	text = "Pause";		break;
		    case fltk::InsertKey: 	text = "Insert";	break;
		    case fltk::HomeKey: 	text = "Home";		break;
		    case fltk::PageUpKey: 	text = "PageUp";	break;
		    case fltk::DeleteKey: 	text = "Delete";	break;
		    case fltk::EndKey: 		text = "End";		break;
		    case fltk::PageDownKey: 	text = "PageDown";	break;
		    case fltk::LeftKey: 	text = "Left";		break;
		    case fltk::UpKey: 		text = "Up";		break;
		    case fltk::RightKey: 	text = "Right";		break;
		    case fltk::DownKey: 	text = "Down";		break;

		    default:
			text = (char*) fltk::event_text();
			break;
		}

		char out[32] = "";

		if (event_state() & fltk::SHIFT)
		    strcat(out, "Shift+");

		if (event_state() & fltk::CTRL)
		    strcat(out, "Ctrl+");

		if (event_state() & fltk::ALT)
		    strcat(out, "Alt+");

		strcat(out, text);

    		DaoMap_InsertMBS(map, "key", DValue_NewMBString(out, 0));

		break;
	    }

	    default:
    		DaoMap_InsertMBS(map, "event", DValue_NewInteger(event));
	}

        item.t = DAO_MAP;
        item.v.map = map;

	DValue arg[] = { item };
	DValue *args[] = { arg };

        DaoVmProcess *vmp = DaoVmSpace_AcquireProcess(VmSpace);
        DaoVmProcess_Call(vmp, val.v.routine, obj, args, 1);

        DaoVmSpace_ReleaseProcess(VmSpace, vmp);
        DValue_ClearAll(arg, 1);
    }

    return 0;
}

//

static void drawbox_new(DaoContext *ctx, DValue *p[], int N) {
    int x = (int) p[0]->v.i;
    int y = (int) p[1]->v.i;
    int w = (int) p[2]->v.i;
    int h = (int) p[3]->v.i;

    CDrawBox *ptr = new CDrawBox(x, y, w, h);
    DaoCData *cdata = DaoContext_PutCData(ctx, ptr, &drawboxTyper);

    ptr->user_data((void*) cdata);
};

static void drawbox_line(DaoContext *ctx, DValue *p[], int N) {
    int x1 = (int) p[1]->v.i;
    int y1 = (int) p[2]->v.i;
    int x2 = (int) p[3]->v.i;
    int y2 = (int) p[4]->v.i;

    fltk::drawline(x1, y1, x2, y2);
}

static void drawbox_strokerect(DaoContext *ctx, DValue *p[], int N) {
    int x1 = (int) p[1]->v.i;
    int y1 = (int) p[2]->v.i;
    int x2 = (int) p[3]->v.i;
    int y2 = (int) p[4]->v.i;

    fltk::strokerect(x1, y1, x2, y2);
}

static void drawbox_fillrect(DaoContext *ctx, DValue *p[], int N) {
    int x1 = (int) p[1]->v.i;
    int y1 = (int) p[2]->v.i;
    int x2 = (int) p[3]->v.i;
    int y2 = (int) p[4]->v.i;

    fltk::fillrect(x1, y1, x2, y2);
}

static void drawbox_drawtext(DaoContext *ctx, DValue *p[], int N) {
    int x = (int) p[1]->v.i;
    int y = (int) p[2]->v.i;
    char *text = (char*) DString_GetMBS(p[3]->v.s);

    fltk::drawtext(text, x, y);
}

static void drawbox_setcolor(DaoContext *ctx, DValue *p[], int N) {
    char *color = (char*) DString_GetMBS(p[1]->v.s);

    fltk::setcolor(fltk::color(color));
}

static void drawbox_linestyle(DaoContext *ctx, DValue *p[], int N) {
    int style = (int) p[1]->v.i;
    int width = (int) p[2]->v.i;

    fltk::line_style(style, width);
}

static void drawbox_addvertex(DaoContext *ctx, DValue *p[], int N) {
    int x = (int) p[1]->v.i;
    int y = (int) p[2]->v.i;

    fltk::addvertex(x, y);
}

static void drawbox_addcurve(DaoContext *ctx, DValue *p[], int N) {
    int x1 = (int) p[1]->v.i;
    int y1 = (int) p[2]->v.i;
    int x2 = (int) p[3]->v.i;
    int y2 = (int) p[4]->v.i;
    int x3 = (int) p[5]->v.i;
    int y3 = (int) p[6]->v.i;
    int x4 = (int) p[7]->v.i;
    int y4 = (int) p[8]->v.i;

    fltk::addcurve(x1,y1, x2,y2, x3,y3, x4,y4);
}

static void drawbox_addarc(DaoContext *ctx, DValue *p[], int N) {
    int x = (int) p[1]->v.i;
    int y = (int) p[2]->v.i;
    int w = (int) p[3]->v.i;
    int h = (int) p[4]->v.i;
    int a1 = (int) p[5]->v.i;
    int a2 = (int) p[6]->v.i;

    fltk::addarc(x,y, w,h, a1,a2);
}

static void drawbox_strokepath(DaoContext *ctx, DValue *p[], int N) {
    fltk::strokepath();
}

static void drawbox_fillstrokepath(DaoContext *ctx, DValue *p[], int N) {
    char *color = (char*) DString_GetMBS(p[1]->v.s);

    fltk::fillstrokepath(fltk::color(color));
}

//

static DaoFuncItem drawboxMeth[] = {
    { drawbox_new, 		"fltk_drawbox(x:int, y:int, w:int, h:int)" },

    { drawbox_line, 		"line(self:fltk_drawbox, x1:int, y1:int, x2:int, y2:int)" },
    { drawbox_strokerect, 	"strokerect(self:fltk_drawbox, x1:int, y1:int, x2:int, y2:int)" },
    { drawbox_fillrect, 	"fillrect(self:fltk_drawbox, x1:int, y1:int, x2:int, y2:int)" },
    { drawbox_drawtext, 	"drawtext(self:fltk_drawbox, x:int, y:int, text:string)" },
    { drawbox_setcolor, 	"setcolor(self:fltk_drawbox, color:string)" },
    { drawbox_linestyle, 	"linestyle(self:fltk_drawbox, style:int, width:int)" },

    { drawbox_addvertex, 	"addvertex(self:fltk_drawbox, x:int, y:int)" },
    { drawbox_addcurve, 	"addcurve(self:fltk_drawbox, x1:int, y1:int, x2:int, y2:int, x3:int, y3:int, x4:int, y4:int)" },
    { drawbox_addarc, 		"addarc(self:fltk_drawbox, x:int, y:int, w:int, h:int, a1:int = 0, a2:int = 360)" },
    { drawbox_strokepath, 	"strokepath(self:fltk_drawbox)" },
    { drawbox_fillstrokepath, 	"fillstrokepath(self:fltk_drawbox, color:string)" },

    { NULL, NULL }
};

static DaoNumItem drawboxConst[] = {
    { "SOLID", 		DAO_INTEGER, fltk::SOLID },
    { "DASH",		DAO_INTEGER, fltk::DASH },
    { "DOT", 		DAO_INTEGER, fltk::DOT },
    { "DASHDOT", 	DAO_INTEGER, fltk::DASHDOT },
    { "DASHDOTDOT", 	DAO_INTEGER, fltk::DASHDOTDOT },

    { "CAP_FLAT", 	DAO_INTEGER, fltk::CAP_FLAT },
    { "CAP_ROUND", 	DAO_INTEGER, fltk::CAP_ROUND },
    { "CAP_SQUARE", 	DAO_INTEGER, fltk::CAP_SQUARE },

    { "JOIN_MITER", 	DAO_INTEGER, fltk::JOIN_MITER },
    { "JOIN_ROUND", 	DAO_INTEGER, fltk::JOIN_ROUND },
    { "JOIN_BEVEL", 	DAO_INTEGER, fltk::JOIN_BEVEL },

    { NULL, 0, 0 }
};

DaoTypeBase drawboxTyper = {
    "fltk_drawbox",
    NULL,
    drawboxConst,               /* constant */
    drawboxMeth,                /* methods */
    { &widgetTyper, NULL },     /* parent type */
    { NULL },
    NULL,
    NULL                        /* free by free() */
};
